package com.brave.commonly;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;

import androidx.annotation.NonNull;
import androidx.core.content.FileProvider;

import com.brave.commonly.utils.ActivityUtils;

import java.lang.reflect.InvocationTargetException;
import java.nio.charset.Charset;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * CommonConfig
 * <br/>
 * {@link @author} brave tao
 * <br/>
 * {@link @time} 2019/7/23
 * <br/>
 * {@link @description} 个人常用配置（全局）
 */
public final class CommonConfig {
    // 维护全局应用程序状态的基类
    private static Application application;
    // 全局应用程序监听
    private static ActivityLifecycleImpl activityLifecycle = new ActivityLifecycleImpl();
    private static final ExecutorService UTIL_POOL = Executors.newFixedThreadPool(3);
    private static final Handler UTIL_HANDLER = new Handler(Looper.getMainLooper());

    private CommonConfig() {
        throw new RuntimeException("cannot be instantiated");
    }

    /**
     * 初始化 个人常用配置
     */
    public static void init(final Context context) {
        if (context == null) {
            init(getApplicationByReflect());
            return;
        }
        init((Application) context.getApplicationContext());
    }

    /**
     * 初始化 个人常用配置
     */
    public static void init(final Application app) {
        if (application == null) {
            if (app == null) {
                application = getApplicationByReflect();
            } else {
                application = app;
            }
            application.registerActivityLifecycleCallbacks(activityLifecycle);
        } else {
            if (app != null && app.getClass() != application.getClass()) {
                application.unregisterActivityLifecycleCallbacks(activityLifecycle);
                ActivityUtils.getInstance().clearActivity();
                application = app;
                application.registerActivityLifecycleCallbacks(activityLifecycle);
            }
        }
    }

    public static Application getApplication() {
        if (null == application) {
            throw new RuntimeException("Use this method(CommonConfig.init(app)) after initialization");
        }
        return application;
    }

    /**
     * 反射获取Application
     */
    private static Application getApplicationByReflect() {
        try {
            @SuppressLint("PrivateApi")
            Class<?> activityThread = Class.forName("android.app.ActivityThread");
            Object thread = activityThread.getMethod("currentActivityThread").invoke(null);
            Object app = activityThread.getMethod("getApplication").invoke(thread);
            if (app == null) {
                throw new NullPointerException("u should init first");
            }
            return (Application) app;
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        throw new NullPointerException("u should init first");
    }

    public static Context getContext() {
        return getApplication().getApplicationContext();
    }

    public static Resources getResources() {
        return getContext().getResources();
    }

    // 默认编码格式
    private static Charset defaultCharset = Charset.forName("UTF-8");

    /**
     * 获取默认编码格式
     */
    public static Charset getDefaultCharset() {
        return CommonConfig.defaultCharset;
    }

    /**
     * 设置默认编码格式
     *
     * @param defaultCharset 编码格式
     */
    public static void setDefaultCharset(@NonNull Charset defaultCharset) {
        CommonConfig.defaultCharset = defaultCharset;
    }

    /**
     * 设置默认编码格式
     *
     * @param defaultCharset 编码格式
     */
    public static void setDefaultCharset(@NonNull String defaultCharset) {
        CommonConfig.defaultCharset = Charset.forName(defaultCharset);
    }

    static class ActivityLifecycleImpl implements Application.ActivityLifecycleCallbacks {
        @Override
        public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
            // 把本 Activity 加入存活集合中
            ActivityUtils.getInstance().addActivity(activity);
        }

        @Override
        public void onActivityStarted(Activity activity) {
        }

        @Override
        public void onActivityResumed(Activity activity) {
        }

        @Override
        public void onActivityPaused(Activity activity) {
        }

        @Override
        public void onActivityStopped(Activity activity) {
        }

        @Override
        public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
        }

        @Override
        public void onActivityDestroyed(Activity activity) {
            // 把本 Activity 从存活集合中移除并杀死
            ActivityUtils.getInstance().removeActivity(activity);
        }
    }

    /**
     * 异步处理
     *
     * @param task 任务
     * @param <T>  泛型
     */
    public static <T> Task<T> doAsync(final Task<T> task) {
        UTIL_POOL.execute(task);
        return task;
    }

    /**
     * 执行线程
     *
     * @param runnable 线程
     */
    public static void runOnUiThread(final Runnable runnable) {
        if (Looper.myLooper() == Looper.getMainLooper()) {
            runnable.run();
        } else {
            UTIL_HANDLER.post(runnable);
        }
    }

    /**
     * 延时执行线程
     *
     * @param runnable    线程
     * @param delayMillis 延时（ms）
     */
    public static void runOnUiThreadDelayed(final Runnable runnable, long delayMillis) {
        UTIL_HANDLER.postDelayed(runnable, delayMillis);
    }

    ///////////////////////////////////////////////////////////////////////////
    // provider
    ///////////////////////////////////////////////////////////////////////////

    public static final class FileProviderHelper extends FileProvider {
        @Override
        public boolean onCreate() {
            CommonConfig.init(getContext());
            return true;
        }
    }

    ///////////////////////////////////////////////////////////////////////////
    // interface
    ///////////////////////////////////////////////////////////////////////////

    public abstract static class Task<Result> implements Runnable {
        private static final int NEW = 0;
        private static final int COMPLETING = 1;
        private static final int CANCELLED = 2;
        private static final int EXCEPTIONAL = 3;

        private volatile int state = NEW;

        public abstract Result doInBackground();

        private Callback<Result> mCallback;

        public Task(final Callback<Result> callback) {
            mCallback = callback;
        }

        @Override
        public void run() {
            try {
                final Result t = doInBackground();
                if (state != NEW) {
                    return;
                }
                state = COMPLETING;
                UTIL_HANDLER.post(new Runnable() {
                    @Override
                    public void run() {
                        mCallback.onCall(t);
                    }
                });
            } catch (Throwable th) {
                if (state != NEW) return;
                state = EXCEPTIONAL;
            }
        }

        public void cancel() {
            state = CANCELLED;
        }

        public boolean isDone() {
            return state != NEW;
        }

        public boolean isCanceled() {
            return state == CANCELLED;
        }
    }

    public interface Callback<T> {
        void onCall(T data);
    }
}